package search2;

import agents.AutomatonAgent;
import env.Action;
import env.Enviroment;
import env.Orientation;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author orcas
 */
public class Agent2 {

    private String name;
    public int score = 0;
    private AgentState state;
    LinkedList<Action> plan = new LinkedList<Action>();
    private int expanded_nodes = 0;
    private MyQueue queue;

    public Agent2(String name, int row, int col, Orientation orientation, MyQueue queue) {
        this.name = name;
        this.state = new AgentState(row, col, orientation);
        this.queue=queue;
    }

    public String getName() {
        return name;
    }

    public int getScore() {
        return score;
    }

    public AgentState getState() {
        return state;
    }

    public Action getMove() {
        if (plan == null || plan.isEmpty()) {
            rePlan();
        }
        if (plan == null || plan.isEmpty()) {
            return null;
        }
        return plan.removeFirst();
    }

    public void rePlan() {

        System.out.println("before replanning, my performance measure is " + Enviroment.f + "*" + score + " - " + expanded_nodes + " = " + ((Enviroment.f * score) - expanded_nodes));
        //FullBFS : before replanning, my performance measure is 10*183 - 194133 = -192303
        long start=System.currentTimeMillis();
        //expanded_nodes+=treeSearch(queue, state, plan);
        graphSearch();
        long finish=System.currentTimeMillis();
        
        if (plan .isEmpty()) {
            System.out.println("i couldn't come up with a plan :(");
        } else {
            System.out.println("my new plan |" + plan.size() + "| is " + plan);
            
        }
        System.out.println("planning time=" + (finish-start));
        //System.exit(0);
        try {
            System.out.println("press enter to confirm!");
            System.in.read();
        } catch (IOException ex) {
            Logger.getLogger(Agent2.class.getName()).log(Level.SEVERE, null, ex);
        }


    }

    /**********************************************************************
     **********************************************************************
     * 
     *        STATIC  search-related stuff
     * 
     ***********************************************************************
     ***********************************************************************
     */
    public static boolean goalTest(Node2 n) {
        return n.remainingFlags() == 0 || !n.getState().isAlive;
    }
    
    
    
    public void graphSearch(){
        final AutomatonAgent sentry = Enviroment.env.getSentry();
        //glue code:
        AgentState sentry_state = new AgentState(sentry.getRow(), sentry.getCol(), sentry.getOrientation());
        State2 initalState = new State2(state, sentry_state, Enviroment.env.flags, true);
        Node2 root = new Node2(null, null, 0, 0, initalState);
        //PQ2 queue=new PQ2();
        plan.clear();
        HashSet<Node2> closed = new HashSet<Node2>();
        queue.add(root);
        closed.add(root);
        int c = 0;
        while (!queue.isEmpty()) {
            Node2 node = queue.poll();
            if (goalTest(node)) {
                System.out.println("@@@@ after " + c + " iteration, search has finished with " + node);
                node.getActionPath(plan);
                return;
            }

            List<Node2> expand = node.expand();
            for (Node2 n : expand) {
                if(!closed.contains(n)) {
                    queue.add(n);
                    closed.add(n);
                    expanded_nodes++;
                // System.out.print ("#"+n.id+", ");
                }
            }
            c++;
        }

        //now node is a goal node:
        System.out.println("@@@@ after " + c + " iteration, search has found no goal! @@@@");
        return ;
    }
}
